use crate::window::Window;
use ncurses::*;
use crate::data::ContentChar;

#[repr(u8)]
pub enum Keymap {
    #[allow(dead_code)]
    CtrlA = 1_u8,
    #[allow(dead_code)]
    CtrlB,
    #[allow(dead_code)]
    CtrlC,
    #[allow(dead_code)]
    CtrlD,
    #[allow(dead_code)]
    CtrlE,
    #[allow(dead_code)]
    CtrlF,
    #[allow(dead_code)]
    CtrlG,
    #[allow(dead_code)]
    CtrlH,
    #[allow(dead_code)]
    CtrlI,
    #[allow(dead_code)]
    CtrlJ,
    #[allow(dead_code)]
    CtrlK,
    #[allow(dead_code)]
    CtrlL,
    #[allow(dead_code)]
    CtrlM,
    #[allow(dead_code)]
    CtrlN,
    #[allow(dead_code)]
    CtrlO,
    #[allow(dead_code)]
    CtrlP,
    #[allow(dead_code)]
    CtrlQ,
    #[allow(dead_code)]
    CtrlR,
    #[allow(dead_code)]
    CtrlS,
    #[allow(dead_code)]
    CtrlT,
    #[allow(dead_code)]
    CtrlU,
    #[allow(dead_code)]
    CtrlV,
    #[allow(dead_code)]
    CtrlW,
    #[allow(dead_code)]
    CtrlX,
    #[allow(dead_code)]
    CtrlY,
    #[allow(dead_code)]
    CtrlZ
}

pub fn set_keymap(ui: &Vec<Window>, content_chars: Vec<Vec<ContentChar>>) {
    let file_explorer: &Window = ui.get(0).unwrap();
    let editor: &Window = ui.get(1).unwrap();
    let mut is_edit: bool = true;
    let mut editor_xy: (i32, i32) = (1, 1);
    // let mut content_xy: (i32, i32) = (0, 0);
    let ascii_chars: [char; 33] = [
        '`', '~',
        '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+',
        '[', ']', '\\', '{', '}', '|',
        ';', ':', '\'', '"',
        ',', '<', '.', '>', '/', '?', ' '
    ];
    let mut current_xy: (i32, i32) = (1, 1);
    wmove((*editor).win, editor_xy.1, editor_xy.0);
    loop {
        let ch: i32 = getch();
        let ch_u8: u8 = ch as u8;
        if ch == Keymap::CtrlQ as i32 {  // Ctrl + Q
            break;
        } else if ch == KEY_F1 || ch == Keymap::CtrlE as i32 {
            if is_edit {
                is_edit = false;
                mv(1, 1);
            }
        } else if ch == KEY_F2 || ch == Keymap::CtrlT as i32 {
            if !is_edit {
                is_edit = true;
                mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
            }
        } else if ch == KEY_LEFT {
            if is_edit {
                if editor_xy.0 > 1 {
                    editor_xy.0 -= 1;
                    mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                } else if editor_xy.1 > 1 {
                    editor_xy.0 = content_chars.get((editor_xy.1 - 1) as usize).unwrap().len() as i32;
                    editor_xy.1 -= 1;
                    mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                }
            }
        } else if ch == KEY_RIGHT {
            if is_edit {
                if current_xy.1 > content_chars.len() as i32 {
                    continue;
                }
                let current_line_chars: &Vec<ContentChar> = content_chars.get(current_xy.1 as usize - 1).unwrap();
                let current_len: i32 = current_line_chars.len() as i32;
                if current_xy.0 > current_len {
                    continue;
                }
                let current_char: &ContentChar = (*current_line_chars).get(current_xy.0 as usize - 1).unwrap();
                if current_char.ch == '\0' {
                    continue;
                }
                mvwaddstr((*file_explorer).win, 1, 1, format!("{:?}", current_xy).as_str());
                wrefresh((*file_explorer).win);
                let current_x: i32 = current_char.column_index as i32;
                if editor_xy.0 < (*editor).width - 2 && current_char.ch != '\n' {
                    editor_xy.0 += 1;
                    current_xy.0 += 1;
                    mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                } else if editor_xy.1 < (*editor).height - 2 &&
                    (editor_xy.0 >= (*editor).width - 2 || editor_xy.0 + 1 >= current_x) &&
                    current_xy.1 < content_chars.len() as i32 {
                    editor_xy.0 = 1;
                    editor_xy.1 += 1;
                    if current_xy.0 >= current_len {
                        current_xy.0 = 1;
                        current_xy.1 += 1;
                    }
                    mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                }
            }
        } else if ch == KEY_UP {
            if is_edit {
                if current_xy.1 > 1 {
                    current_xy.1 -= 1;
                    let current_line_chars: &Vec<ContentChar> = content_chars.get(current_xy.1 as usize - 1).unwrap();
                    if current_xy.0 + 1 <= (*current_line_chars).len() as i32 {
                        let ch: &ContentChar = (*current_line_chars).get(current_xy.0 as usize - 1).unwrap();
                        let line_index: i32 = (*ch).line_index as i32;
                        if editor_xy.1 > 1 && current_xy.1 >= 1 {
                            editor_xy.1 = line_index;
                            mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                        }
                    }
                }
            }
        } else if ch == KEY_DOWN {
            if is_edit {
                if current_xy.1 < content_chars.len() as i32 {
                    current_xy.1 += 1;
                    let current_line_chars: &Vec<ContentChar> = content_chars.get(current_xy.1 as usize - 1).unwrap();
                    if current_xy.0 <= (*current_line_chars).len() as i32 {
                        let ch: &ContentChar = (*current_line_chars).get(current_xy.0 as usize - 1).unwrap();
                        let line_index: i32 = (*ch).line_index as i32;
                        if editor_xy.1 < (*editor).height - 2 && current_xy.1 - 1 <= (*editor).height - 2 {
                            editor_xy.1 = line_index;
                            mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                        }
                    }
                }
            }
        } else if (ch >= '0' as i32 && ch <= '9' as i32) ||
            (ch >= 'a' as i32 && ch <= 'z' as i32) ||
            (ch >= 'A' as i32 && ch <= 'Z' as i32) ||
            ascii_chars.contains(&(ch_u8 as char)) {
            attron(COLOR_PAIR((*editor).color_id));
            waddch((*editor).win, ch_u8 as chtype);
            attroff(COLOR_PAIR((*editor).color_id));
            wrefresh((*editor).win);
            if editor_xy.0 < (*editor).width - 2 {
                editor_xy.0 += 1;
                mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
            } else if editor_xy.1 < (*editor).height - 2 {
                editor_xy.0 = 1;
                editor_xy.1 += 1;
                mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
            }
        } else if ch == KEY_BACKSPACE {
            if is_edit {
                if editor_xy.0 > 1 {
                    editor_xy.0 -= 1;
                    mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                } else if editor_xy.1 > 1 {
                    editor_xy.0 = (*editor).width - 2;
                    editor_xy.1 -= 1;
                    mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                }
            }
        } else if ch == 10 || ch == 13 {
            if is_edit {
                if editor_xy.1 < (*editor).height - 2 {
                    editor_xy.0 = 1;
                    editor_xy.1 += 1;
                    mv(editor_xy.1, (*file_explorer).width + editor_xy.0);
                }
            }
        }
        wmove((*editor).win, editor_xy.1, editor_xy.0);
    }
}
